#pragma once

#include <iostream>
#include <fstream>
#include <string>
#include <mutex>
#include <sstream>
#include <chrono>
#include <iomanip>
#include <functional>
#include <atomic>
#include <thread>

namespace SeanNetwork {

// 日志级别定义
enum class LogLevel {
    Debug,      // 调试信息
    Info,       // 正常信息
    Warning,    // 警告信息
    Error,      // 错误信息
    Fatal       // 致命错误
};

// 日志输出回调类型
using LogCallback = std::function<void(LogLevel level, const std::string& message)>;

/**
 * @brief 日志系统类
 * 
 * 线程安全的日志系统，支持控制台输出和文件输出
 */
class Logger {
public:
    /**
     * @brief 获取日志系统单例
     * @return 日志系统单例引用
     */
    static Logger& GetInstance() {
        static Logger instance;
        return instance;
    }
    
    /**
     * @brief 初始化日志系统
     * @param logLevel 日志级别
     * @param logToFile 是否输出到文件
     * @param logFile 日志文件路径，为空则使用默认路径
     * @return 是否成功初始化
     */
    bool Initialize(LogLevel logLevel = LogLevel::Info, bool logToFile = false, const std::string& logFile = "");
    
    /**
     * @brief 关闭日志系统
     */
    void Shutdown();
    
    /**
     * @brief 设置日志级别
     * @param level 日志级别
     */
    void SetLogLevel(LogLevel level);
    
    /**
     * @brief 获取当前日志级别
     * @return 当前日志级别
     */
    LogLevel GetLogLevel() const;
    
    /**
     * @brief 设置额外的日志回调
     * @param callback 回调函数
     */
    void SetCallback(LogCallback callback);
    
    /**
     * @brief 写入日志
     * @param level 日志级别
     * @param message 日志内容
     */
    void Log(LogLevel level, const std::string& message);
    
    /**
     * @brief 写入调试日志
     * @param message 日志内容
     */
    void Debug(const std::string& message);
    
    /**
     * @brief 写入普通信息日志
     * @param message 日志内容
     */
    void Info(const std::string& message);
    
    /**
     * @brief 写入警告日志
     * @param message 日志内容
     */
    void Warning(const std::string& message);
    
    /**
     * @brief 写入错误日志
     * @param message 日志内容
     */
    void Error(const std::string& message);
    
    /**
     * @brief 写入致命错误日志
     * @param message 日志内容
     */
    void Fatal(const std::string& message);
    
private:
    // 私有构造函数，确保单例模式
    Logger();
    
    // 禁止复制和赋值
    Logger(const Logger&) = delete;
    Logger& operator=(const Logger&) = delete;
    
    /**
     * @brief 日志级别转字符串
     * @param level 日志级别
     * @return 日志级别字符串
     */
    static std::string LogLevelToString(LogLevel level);
    
    std::atomic<bool> m_Initialized;        // 是否已初始化
    std::atomic<LogLevel> m_LogLevel;       // 日志级别
    bool m_LogToFile;                       // 是否输出到文件
    std::string m_LogFilePath;              // 日志文件路径
    std::ofstream m_LogFile;                // 日志文件流
    std::mutex m_Mutex;                     // 互斥锁，保护写入操作
    LogCallback m_Callback;                 // 日志回调函数
};

// 便捷宏，用于快速写日志
#define LOG_DEBUG(msg) SeanNetwork::Logger::GetInstance().Debug(msg)
#define LOG_INFO(msg) SeanNetwork::Logger::GetInstance().Info(msg)
#define LOG_WARNING(msg) SeanNetwork::Logger::GetInstance().Warning(msg)
#define LOG_ERROR(msg) SeanNetwork::Logger::GetInstance().Error(msg)
#define LOG_FATAL(msg) SeanNetwork::Logger::GetInstance().Fatal(msg)

} // namespace SeanNetwork 